package com.gzdh.tang.dishrecognition.rule;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePayRequest;
import com.alipay.api.response.AlipayTradePayResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.gzdh.tang.ali.model.OuterExtends;
import com.gzdh.tang.comm.constant.SpringContextUtils;
import com.gzdh.tang.comm.handler.IPayRuleHandler;
import com.gzdh.tang.config.ali.AliPayUtil;
import com.gzdh.tang.dishrecognition.model.PayModelReq;
import com.gzdh.tang.dishrecognition.model.WeekMenuBakModelReq;
import com.gzdh.tang.mobile.entity.Kl;
import com.gzdh.tang.mobile.service.KlService;
import com.gzdh.tang.modu.entity.*;
import com.gzdh.tang.modu.model.QrRestrictionsModel;
import com.gzdh.tang.modu.model.dk.JsonsRootBean;
import com.gzdh.tang.modu.service.*;
import com.gzdh.tang.modu.util.DateUtil;
import com.gzdh.tang.warehouse.service.DeviceService;
import com.gzdh.tang.warehouse.service.InStockService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Date;
import java.util.List;

@Slf4j
public class DrTedcPaytRule implements IPayRuleHandler {


    FkService fkService;

    GsService gsService;

    MacMainpSbruanService macMainpSbruanService;

    MacMainpSbruanDinnerService macMainpSbruanDinnerService;

    MacMainpSbruanKlService macMainpSbruanKlService;

    ReserveService reserveService;

    TangDeviceService tangDeviceService;

    DeviceService deviceService;

    InStockService inStockService;

    KlService klService;

    ReserveXfjTempService reserveXfjTempService;

    TangAddrService tangAddrService;

    public DrTedcPaytRule() {
        fkService = (FkService) SpringContextUtils.getBean("fkServiceImpl");
        gsService = (GsService) SpringContextUtils.getBean("gsService");
        macMainpSbruanService = (MacMainpSbruanService) SpringContextUtils.getBean("macMainpSbruanService");
        macMainpSbruanDinnerService = (MacMainpSbruanDinnerService) SpringContextUtils.getBean("macMainpSbruanDinnerService");
        macMainpSbruanKlService = (MacMainpSbruanKlService) SpringContextUtils.getBean("macMainpSbruanKlService");
        reserveService = (ReserveService) SpringContextUtils.getBean("reserveService");
        tangDeviceService = (TangDeviceService) SpringContextUtils.getBean("tangDeviceServiceImpl");
        deviceService = (DeviceService) SpringContextUtils.getBean("deviceServiceImpl");
        inStockService = (InStockService) SpringContextUtils.getBean("inStockService");
        klService = (KlService) SpringContextUtils.getBean("klService");
        reserveXfjTempService = (ReserveXfjTempService) SpringContextUtils.getBean("reserveServiceXfjTemp");
        tangAddrService = (TangAddrService) SpringContextUtils.getBean("tangAddrServiceImpl");
    }

    @Override
    public JSONObject toCardPay(JSONObject params) throws RuntimeException {
        PayModelReq payModelReq = params.toJavaObject(PayModelReq.class);
        MacMainpSbruan macMainpSbruan = macMainpSbruanService.getOne(new QueryWrapper<MacMainpSbruan>().lambda()
                .eq(MacMainpSbruan::getMac, payModelReq.getDeviceId()));
        String orders = payModelReq.getOrders();
        boolean ignoreException = payModelReq.getIgnoreException() == null ? false : payModelReq.getIgnoreException();
        String posnum=params.getString("userId");
        if (macMainpSbruan.getUsePostType() == 0) {
            posnum = macMainpSbruan.getPos();
        }
        macMainpSbruan.setPos(posnum);
        Fk fk = null;
        String fl = null;
        QrRestrictionsModel qrRestrictionsModel = JSONObject.toJavaObject(JSONObject.parseObject(macMainpSbruan.getQrRestrictions()), QrRestrictionsModel.class);
        if (payModelReq.getAuth().length() < 10) {
            //刷卡获取到cardsn
            String cardsnStr = payModelReq.getAuth().toUpperCase();
            fk = fkService.getOne(new QueryWrapper<Fk>().lambda().eq(Fk::getCardsn, cardsnStr));
        } else {
            fl = "1";
            switch (qrRestrictionsModel.getDzkRestrictions()) {
                case 0:
                    throw new RuntimeException("当前模式尚未开通");
                case 1:
                    //通过电子卡解析出来，通过cardNo查询
                    String authStr = payModelReq.getAuth().trim();
                    log.info("解码前：" + authStr);
                    byte[] bytes = Base64.getDecoder().decode(payModelReq.getAuth());
                    String json = new String(bytes);
                    try {
                        log.info("解码后：" + json);
                        String cardNo = json.split(",")[0].split("=")[1];
                        String dates = json.split(",")[2].split("=")[1];
                        String nowDate = new SimpleDateFormat("yyyyMMddHHmmss")
                                .format(new Date(System.currentTimeMillis() - (2 * (60 * 1000) * 60)));
                        if (new BigDecimal(nowDate).compareTo(new BigDecimal(dates)) > 0) {
                            throw new RuntimeException("二维码已过期");
                        }
                        fk = fkService.getOne(new QueryWrapper<Fk>().lambda().eq(Fk::getCardno, cardNo));
                    } catch (Exception e) {
                        e.printStackTrace();
                        throw new RuntimeException(e.getMessage());
                    }
                    break;
                case 2:
                    //通过数据库读取，获取一次解码
                    fk = fkService.getFkByQr2(payModelReq.getAuth());
                    break;
            }
        }
        if (fk == null) {
            if(!ignoreException) {
                throw new RuntimeException("查无此人");
            }
        }
        List<String> tsdcList = fkService.getTsdc(macMainpSbruan.getPos());
        if (tsdcList != null && tsdcList.size() > 0) {
            String sfbm = fk.getSfbm();
            String str = tsdcList.stream().filter(s -> sfbm.trim().equals(s.trim())).findFirst().orElse(null);
            if (StringUtils.isNotEmpty(str)) {
                if(!ignoreException) {
                    throw new RuntimeException("该卡时间段无法消费");
                }
            }
        }
        int count = gsService.count(new QueryWrapper<Gs>().lambda().eq(Gs::getKh, fk.getKh()).eq(Gs::getCardno, fk.getCardno()));
        if (count > 0 && !"1".equals(fl)) {
            if(!ignoreException) {
                throw new RuntimeException("此卡已挂失");
            }
        }
        List<MacMainpSbruanKl> macMainpSbruanKlList = macMainpSbruanKlService.list(new QueryWrapper<MacMainpSbruanKl>().lambda()
                .eq(MacMainpSbruanKl::getDeviceId, macMainpSbruan.getId()));
        if (!judeKl(macMainpSbruanKlList, fk.getKl())) {
            if(!ignoreException) {
                throw new RuntimeException("此卡类不许消费");
            }
        }

        Kl kl = klService.getOne(new QueryWrapper<Kl>().lambda().eq(Kl::getBm, fk.getKl()));
        if (kl != null && kl.getValid() == 1) {
            //判断有效期
            if (fk.getValiddate().compareTo(new Date()) < 0) {
                if(!ignoreException) {
                    throw new RuntimeException("此卡已超过有效期");
                }
            }
        }
        int sc = 0;
        BigDecimal totalBalance = new BigDecimal(0);
        if (new BigDecimal(fk.getBtye()).compareTo(payModelReq.getAmountPriceSum()) >= 0) {
            sc = 1;
            totalBalance = new BigDecimal(fk.getBtye());
            BigDecimal btYe = new BigDecimal(fk.getBtye()).subtract(payModelReq.getAmountPriceSum());
            fk.setBtye(btYe.setScale(2, BigDecimal.ROUND_DOWN).toPlainString());
        } else if (new BigDecimal(fk.getKye()).compareTo(payModelReq.getAmountPriceSum()) >= 0) {
            totalBalance = new BigDecimal(fk.getKye());
            BigDecimal kye = new BigDecimal(fk.getKye()).subtract(payModelReq.getAmountPriceSum());
            fk.setKye(kye.setScale(2, BigDecimal.ROUND_DOWN).toPlainString());
        } else {
            if(!ignoreException) {
                throw new RuntimeException("余额不足");
            }
        }
        if(ignoreException) {
            sc = payModelReq.getSc();
        }
        Date date = payModelReq.getCzrq() != null ? payModelReq.getCzrq() : new Date();
        int i = 0;
        String dinner = getDinner(macMainpSbruan, date).trim();
        List<WeekMenuBakModelReq> weekMenuBakModelReqs = new ArrayList<>();
        for (WeekMenuBakModelReq goo : payModelReq.getProductCartModelList()) {
            if ("xjc".equals(goo.getBm())) {
                WeekMenuBakModelReq weekMenuBakModelReq = weekMenuBakModelReqs.stream()
                        .filter(weekMenuBakModelReq1 -> "xjc".equals(weekMenuBakModelReq1.getBm())).findFirst().orElse(null);
                if (weekMenuBakModelReq != null) {
                    weekMenuBakModelReq.setPrice(new BigDecimal(weekMenuBakModelReq.getPrice())
                            .add(new BigDecimal(goo.getPrice())).toPlainString());
                } else {
                    weekMenuBakModelReqs.add(goo);
                }
            } else {
                weekMenuBakModelReqs.add(goo);
            }
        }
        payModelReq.setProductCartModelList(weekMenuBakModelReqs);
        for (WeekMenuBakModelReq goo : payModelReq.getProductCartModelList()) {
            i++;
            if ("xjc".equals(goo.getBm())) {
                goo.setBm(macMainpSbruan.getCode());
                goo.setZl(macMainpSbruan.getZl());
            }
            Reserve reserve = new Reserve();
            reserve.setCardno(fk.getCardno());
            reserve.setZl(goo.getZl());
            reserve.setBqh(macMainpSbruan.getBqh());
            reserve.setKsh(macMainpSbruan.getKsh());
            reserve.setBed("0");
            reserve.setPosnum(macMainpSbruan.getPos());
            reserve.setDinner(dinner);
            reserve.setCode(goo.getBm());
            reserve.setSl(goo.getNumber());
            reserve.setJe(new BigDecimal(goo.getNumber()).multiply(new BigDecimal(goo.getPrice())).toPlainString());
            reserve.setYe(totalBalance.subtract(new BigDecimal(reserve.getJe())).toPlainString());
            reserve.setKl(fk.getKl());
            reserve.setSc(String.valueOf(sc));
            reserve.setLsh2(orders);
            reserve.setCzrq(new Date(date.getTime() + (i * 10)));
            reserve.setDcrq(new SimpleDateFormat("yyyy-MM-dd 00:00:00").format(new Date(date.getTime())));
            reserve.setHname(goo.getName());
            reserve.setSddz(payModelReq.getDeviceId());
            reserve.setCs(0);
            reserve.setTmpFieldZk(fl);
            reserve.setKehu(fk.getName());
            reserve.setStatus("1");
            reserve.setZfserialnumber(orders);
            reserve.setAddr(macMainpSbruan.getAddr());
            reserveService.save(reserve);
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("fk", fk);
        jsonObject.put("success", true);
        jsonObject.put("msg", "支付成功");
        jsonObject.put("userName", fk.getName());
        jsonObject.put("posnum", posnum);
        jsonObject.put("amount", payModelReq.getAmountPriceSum().toPlainString());
        List<OuterExtends> outerExtendsList = new ArrayList<>();
        outerExtendsList.add(addOutOuterExtends("姓名", fk.getName()));
        outerExtendsList.add(addOutOuterExtends("消费金额", payModelReq.getAmountPriceSum().toPlainString()));
        outerExtendsList.add(addOutOuterExtends("卡余额", fk.getKye()));
        outerExtendsList.add(addOutOuterExtends("补贴余额", fk.getBtye()));
        jsonObject.put("outerExtends", outerExtendsList);
        return jsonObject;
    }

    private String getDinner(MacMainpSbruan macMainpSbruan, Date date) throws RuntimeException {
        try {
            String hourMin = new SimpleDateFormat("HH:mm").format(date);
            List<MacMainpSbruanDinner> macMainpSbruanDinnerList = macMainpSbruanDinnerService
                    .list(new QueryWrapper<MacMainpSbruanDinner>().lambda().eq(MacMainpSbruanDinner::getDeviceId, macMainpSbruan.getId()));
            for (MacMainpSbruanDinner goo : macMainpSbruanDinnerList) {
                if (DateUtil.hourMinuteBetween(hourMin, goo.getStartTime(), goo.getEndTime())) {
                    return goo.getDinner();
                }
            }
            throw new Exception("未找到该餐次");
        } catch (Exception ex) {
            ex.printStackTrace();
            throw new RuntimeException(ex.getMessage());
        }


    }

    private boolean judeKl(List<MacMainpSbruanKl> macMainpSbruanKlList, String kl) {
        for (MacMainpSbruanKl goo : macMainpSbruanKlList) {
            if (goo.getKl().equals(kl.trim())) {
                return true;
            }
        }
        return false;
    }

    @Override
    public JSONObject toCashPay(JSONObject params) throws RuntimeException {
        return null;
    }

    @Override
    public JSONObject toQrPay(JSONObject params) throws RuntimeException {
        return null;
    }

    @Override
    public JSONObject toFacePay(JSONObject params) throws RuntimeException {
        //刷脸支付
        PayModelReq payModelReq = params.toJavaObject(PayModelReq.class);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String orders = "FACE" + sdf.format(new Date()) + payModelReq.getAliUid().substring(0, 4);
        JSONObject jsonObject = new JSONObject();
        jsonObject.putAll(params);
        try {

            Fk fk = fkService.getOne(new QueryWrapper<Fk>().lambda().eq(Fk::getAliUserId, payModelReq.getAliUid()));
            if (fk == null) {
                throw new RuntimeException("查无此人");
            }
            String enterprisePayAmount = "0.00";
            MacMainpSbruan macMainpSbruan = macMainpSbruanService.getOne(new QueryWrapper<MacMainpSbruan>().lambda()
                    .eq(MacMainpSbruan::getMac, payModelReq.getDeviceId()));
            String posnum=params.getString("userId");
            if (macMainpSbruan.getUsePostType() == 0) {
                posnum = macMainpSbruan.getPos();
            }
            macMainpSbruan.setPos(posnum);
            Addr addr = tangAddrService.getOne(new QueryWrapper<Addr>().lambda().eq(Addr::getAddrNo, macMainpSbruan.getAddr()));


            int sc = 0;
            if (new BigDecimal(fk.getBtye()).compareTo(payModelReq.getAmountPriceSum()) >= 0) {
                sc = 1;
                enterprisePayAmount = payModelReq.getAmountPriceSum().toPlainString();
            } else if (new BigDecimal(fk.getKye()).compareTo(payModelReq.getAmountPriceSum()) >= 0) {
                sc = 0;
                enterprisePayAmount = payModelReq.getAmountPriceSum().toPlainString();
            } else {
                sc = 4;
            }
            try {
                AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do",
                        AliPayUtil.getAppid(), AliPayUtil.getPrivateKey(),
                        "json", "GBK", AliPayUtil.getPublicKey(),
                        "RSA2");
                AlipayTradePayRequest request = new AlipayTradePayRequest();
                JsonsRootBean jsonsRootBean = new JsonsRootBean(orders, payModelReq.getAmountPriceSum().toPlainString(),
                        payModelReq.getFaceToken(), AliPayUtil.getAssignJointAccountId(), enterprisePayAmount, payModelReq.getTerminal_params());
                request.setBizContent(JSONObject.toJSONString(jsonsRootBean));
                AlipayTradePayResponse response = alipayClient.execute(request, null, addr.getAliAppAuthToken());
                if (!response.isSuccess()) {
                    throw new RuntimeException("支付失败");
                }
                if (!response.getEnterprisePayInfo().getIsUseEnterprisePay()) {
                    sc = 4;
                }

                Date date = payModelReq.getCzrq() != null ? payModelReq.getCzrq() : new Date();
                int i = 0;
                String dinner = getDinner(macMainpSbruan, date).trim();
                if ("xjc".equals(payModelReq.getProductCartModelList().get(0).getBm())) {
                    payModelReq.getProductCartModelList().get(0).setBm(macMainpSbruan.getCode());
                    payModelReq.getProductCartModelList().get(0).setZl(macMainpSbruan.getZl());
                }
                for (WeekMenuBakModelReq goo : payModelReq.getProductCartModelList()) {
                    i++;
                    Reserve reserve = new Reserve();
                    reserve.setCardno(fk.getCardno());
                    reserve.setZl(goo.getZl());
                    reserve.setBqh(macMainpSbruan.getBqh());
                    reserve.setKsh(macMainpSbruan.getKsh());
                    reserve.setBed("0");
                    reserve.setPosnum(macMainpSbruan.getPos());
                    reserve.setDinner(dinner);
                    reserve.setCode(goo.getBm());
                    reserve.setSl(goo.getNumber());
                    reserve.setJe(new BigDecimal(goo.getNumber()).multiply(new BigDecimal(goo.getPrice())).toPlainString());
                    reserve.setYe("0");
                    reserve.setKl(fk.getKl());
                    reserve.setSc(String.valueOf(sc));
                    reserve.setLsh2(orders);
                    reserve.setCzrq(new Date(date.getTime() + (i * 10)));
                    reserve.setDcrq(new SimpleDateFormat("yyyy-MM-dd 00:00:00").format(new Date()));
                    reserve.setHname(goo.getName());
                    reserve.setSddz(payModelReq.getDeviceId());
                    reserve.setCs(0);
                    reserve.setKehu(fk.getName());
                    reserve.setStatus("1");
                    reserve.setZfserialnumber(orders);
                    reserve.setAddr(macMainpSbruan.getAddr());
                    reserveService.save(reserve);
                }
                fk = fkService.getOne(new QueryWrapper<Fk>().lambda().eq(Fk::getCardno, fk.getCardno()));
                jsonObject.put("fk", fk);
                jsonObject.put("success", true);
                jsonObject.put("msg", "支付成功");
                jsonObject.put("posnum", posnum);
                jsonObject.put("userName", fk.getName());
                jsonObject.put("amount", payModelReq.getAmountPriceSum().toPlainString());
                List<OuterExtends> outerExtendsList = new ArrayList<>();
                outerExtendsList.add(addOutOuterExtends("姓名", fk.getName()));
                outerExtendsList.add(addOutOuterExtends("消费金额", payModelReq.getAmountPriceSum().toPlainString()));
                outerExtendsList.add(addOutOuterExtends("卡余额", fk.getKye()));
                outerExtendsList.add(addOutOuterExtends("补贴余额", fk.getBtye()));
                jsonObject.put("outerExtends", outerExtendsList);
            } catch (Exception e) {
                throw new RuntimeException("支付失败");
            }
        } catch (RuntimeException exception) {
            exception.printStackTrace();
            jsonObject.put("success", false);
            jsonObject.put("msg", exception.getMessage());
        }

        return jsonObject;
    }


    private OuterExtends addOutOuterExtends(String name, String value) {
        OuterExtends outerExtends = new OuterExtends();
        outerExtends.setTitle(name);
        outerExtends.addDetail(name, value);
        return outerExtends;
    }
}
